﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using ERP.ERPModels.Production.MasterData;
using ERP.MasterData.Dtos;
using Microsoft.Extensions.Logging;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;

namespace ERP.MasterData
{
    public class MaterialService : ApplicationService, IMaterialService
    {
        private readonly IRepository<Material, int> _materialRepository;
        private readonly ILogger<MaterialService> _logger;

        public MaterialService(
            IRepository<Material, int> materialRepository,
            ILogger<MaterialService> logger)
        {
            _materialRepository = materialRepository;
            _logger = logger;
        }

        /// <summary>
        /// 获取物料列表
        /// </summary>
        public async Task<PagedResultDto<MaterialDto>> GetListAsync(GetMaterialInputDto input)
        {
            var query = await CreateFilteredQueryAsync(input);

            var totalCount = query.Count();

            query = ApplySorting(query, input);

            query = query.PageBy(input.SkipCount, input.MaxResultCount);

            var items = query.ToList();

            return new PagedResultDto<MaterialDto>(
                totalCount,
                ObjectMapper.Map<List<Material>, List<MaterialDto>>(items)
            );
        }

        /// <summary>
        /// 获取物料详情
        /// </summary>
        public async Task<MaterialDto> GetAsync(int id)
        {
            var material = await _materialRepository.GetAsync(id);
            return ObjectMapper.Map<Material, MaterialDto>(material);
        }

        /// <summary>
        /// 创建物料
        /// </summary>
        public async Task<MaterialDto> CreateAsync(CreateMaterialDto input)
        {
            // 检查物料编码是否已存在
            var existingMaterial = await _materialRepository.FirstOrDefaultAsync(x => x.MaterielCode == input.MaterielCode);
            if (existingMaterial != null)
            {
                throw new UserFriendlyException("物料编码已存在");
            }

            var material = ObjectMapper.Map<CreateMaterialDto, Material>(input);
            material.CreateTime = DateTime.Now;

            await _materialRepository.InsertAsync(material);
            await CurrentUnitOfWork.SaveChangesAsync();

            return ObjectMapper.Map<Material, MaterialDto>(material);
        }

        /// <summary>
        /// 更新物料
        /// </summary>
        public async Task<MaterialDto> UpdateAsync(int id, UpdateMaterialDto input)
        {
            // 确保id与input.Id一致
            if (id != input.Id && input.Id != 0)
            {
                id = input.Id;
            }

            var material = await _materialRepository.GetAsync(id);

            // 检查物料编码是否已存在（排除自身）
            var existingMaterial = await _materialRepository.FirstOrDefaultAsync(x => x.MaterielCode == input.MaterielCode && x.Id != id);
            if (existingMaterial != null)
            {
                throw new UserFriendlyException("物料编码已存在");
            }

            ObjectMapper.Map(input, material);

            await _materialRepository.UpdateAsync(material);
            await CurrentUnitOfWork.SaveChangesAsync();

            return ObjectMapper.Map<Material, MaterialDto>(material);
        }

        /// <summary>
        /// 删除物料
        /// </summary>
        public async Task DeleteAsync(int id)
        {
            await _materialRepository.DeleteAsync(id);
            await CurrentUnitOfWork.SaveChangesAsync();
        }

        /// <summary>
        /// 批量删除物料
        /// </summary>
        public async Task BatchDeleteAsync(List<int> ids)
        {
            foreach (var id in ids)
            {
                await _materialRepository.DeleteAsync(id);
            }

            await CurrentUnitOfWork.SaveChangesAsync();
        }

        /// <summary>
        /// 生成物料编码
        /// </summary>
        public Task<string> GenerateMaterialCodeAsync()
        {
            // 生成物料编码：M + 年月日时分秒毫秒
            string code = "M" + DateTime.Now.ToString("yyyyMMddHHmmssfff");
            return Task.FromResult(code);
        }

        /// <summary>
        /// 导出物料
        /// </summary>
        public async Task<byte[]> ExportAsync(GetMaterialInputDto input)
        {
            var query = await CreateFilteredQueryAsync(input);
            query = ApplySorting(query, input);
            var items = query.ToList();

            using var ms = new MemoryStream();
            IWorkbook workbook = new XSSFWorkbook();
            ISheet sheet = workbook.CreateSheet("物料产品管理");

            // 创建表头
            var headerRow = sheet.CreateRow(0);
            headerRow.CreateCell(0).SetCellValue("物料编码");
            headerRow.CreateCell(1).SetCellValue("物料名称");
            headerRow.CreateCell(2).SetCellValue("规格型号");
            headerRow.CreateCell(3).SetCellValue("单位");
            headerRow.CreateCell(4).SetCellValue("类型");
            headerRow.CreateCell(5).SetCellValue("所属分类");
            headerRow.CreateCell(6).SetCellValue("是否启用");
            headerRow.CreateCell(7).SetCellValue("是否设置安全库存");
            headerRow.CreateCell(8).SetCellValue("创建时间");

            // 填充数据
            for (int i = 0; i < items.Count; i++)
            {
                var item = items[i];
                var row = sheet.CreateRow(i + 1);
                row.CreateCell(0).SetCellValue(item.MaterielCode);
                row.CreateCell(1).SetCellValue(item.MaterielName);
                row.CreateCell(2).SetCellValue(item.Specifications ?? "");
                row.CreateCell(3).SetCellValue(item.UnitsId);
                row.CreateCell(4).SetCellValue(item.MaterielTypePid == 0 ? "物料" : "产品");
                row.CreateCell(5).SetCellValue(item.MaterielTypeld.ToString());
                row.CreateCell(6).SetCellValue(item.IsNo == 1 ? "启用" : "禁用");
                row.CreateCell(7).SetCellValue(item.IsSecure == 1 ? "是" : "否");
                row.CreateCell(8).SetCellValue(item.CreateTime.ToString("yyyy-MM-dd HH:mm:ss"));
            }

            // 自适应列宽
            for (int i = 0; i < 9; i++)
            {
                sheet.AutoSizeColumn(i);
            }

            workbook.Write(ms);
            return ms.ToArray();
        }

        /// <summary>
        /// 创建过滤查询
        /// </summary>
        private async Task<IQueryable<Material>> CreateFilteredQueryAsync(GetMaterialInputDto input)
        {
            var query = await _materialRepository.GetQueryableAsync();

            // 关键字搜索
            if (!string.IsNullOrWhiteSpace(input.Keyword))
            {
                query = query.Where(x =>
                    x.MaterielCode.Contains(input.Keyword) ||
                    x.MaterielName.Contains(input.Keyword));
            }

            // 物料编码
            if (!string.IsNullOrWhiteSpace(input.MaterielCode))
            {
                query = query.Where(x => x.MaterielCode.Contains(input.MaterielCode));
            }

            // 物料名称
            if (!string.IsNullOrWhiteSpace(input.MaterielName))
            {
                query = query.Where(x => x.MaterielName.Contains(input.MaterielName));
            }

            // 物料/产品类型
            if (input.MaterielTypePid.HasValue)
            {
                query = query.Where(x => x.MaterielTypePid == input.MaterielTypePid.Value);
            }

            // 所属分类
            if (input.MaterielTypeld.HasValue)
            {
                query = query.Where(x => x.MaterielTypeld == input.MaterielTypeld.Value);
            }

            // 是否启用
            if (input.IsNo.HasValue)
            {
                query = query.Where(x => x.IsNo == input.IsNo.Value);
            }

            // 是否设置安全库存
            if (input.IsSecure.HasValue)
            {
                query = query.Where(x => x.IsSecure == input.IsSecure.Value);
            }

            return query;
        }

        /// <summary>
        /// 应用排序
        /// </summary>
        private IQueryable<Material> ApplySorting(IQueryable<Material> query, GetMaterialInputDto input)
        {
            // 如果没有指定排序，默认按照创建时间降序排序
            if (string.IsNullOrWhiteSpace(input.Sorting))
            {
                return query.OrderByDescending(x => x.CreateTime);
            }

            return query.OrderBy(input.Sorting);
        }
        
        /// <summary>
        /// 获取物料类型树
        /// </summary>
        public Task<List<MaterialTypeTreeDto>> GetMaterialTypeTreeAsync()
        {
            // 创建物料/产品根节点
            var result = new List<MaterialTypeTreeDto>
            {
                new MaterialTypeTreeDto
                {
                    Id = 0,
                    title = "物料",
                    ParentId = -1,
                    Children = new List<MaterialTypeTreeDto>
                    {
                        new MaterialTypeTreeDto { Id = 1, title = "原材料", ParentId = 0 },
                        new MaterialTypeTreeDto { Id = 2, title = "半成品", ParentId = 0 }
                    }
                },
                new MaterialTypeTreeDto
                {
                    Id = 1,
                    title = "产品",
                    ParentId = -1,
                    Children = new List<MaterialTypeTreeDto>
                    {
                        new MaterialTypeTreeDto { Id = 3, title = "成品", ParentId = 1 }
                    }
                }
            };

            return Task.FromResult(result);
        }
    }
}
